Repository navigation
[docs] Document the Batcher and CacheKey features - #1728
andrewnicols wants to merge 1 commit into
Conversation
✅ Deploy Preview for moodledevdocs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
🟡 Changes recommended
The documented URLs and minimum-version guidance need correction before developers can reliably use the examples.
3 open findings
What changed in this PR
Adds developer guides for request batching and cacheable routes in Moodle’s REST API.
Changes:
- Documents automatic and manual
core/fetchbatching. - Explains route cache lifetimes, cache keys, headers, and batching interactions.
| File | Description |
|---|---|
| docs/guides/javascript/ajax/batcher.md | Explains batching usage and configuration. |
| docs/apis/subsystems/routing/caching.md | Documents cacheable routes and JavaScript requests. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| - Performance | ||
| --- | ||
|
|
||
| <Since version="6.0" issueNumber="MDL-82652" /> |
|
|
||
| ```php title="A cacheable route" | ||
| #[\core\router\route( | ||
| path: '/strings/{language}/{component}[/{identifier:.*}]', |
| /api/rest/v2/strings/en/core # No cache key - not cached | ||
| /api/rest/v2/cachekey:1737584047/strings/en/core # Cacheable |
477d270 to
b912734
Compare
|
|
||
| `cachelifetime` accepts any relative time string understood by [`DateInterval::createFromDateString()`](https://www.php.net/manual/en/dateinterval.createfromdatestring.php), for example `'90 days'`. | ||
|
|
||
| ```php title="A cacheable route" |
There was a problem hiding this comment.
Should we add cookies: false to the example? Plugin developers will copy it, and without it they'd hit the same bug the strings route had: every request starts a session, and proxies won't cache a response that sets a cookie.
| ```js | ||
| import Fetch from 'core/fetch'; | ||
|
|
||
| const response = await Fetch.performGet('core', `strings/en/core`, {cachekey: M.cfg.jsrev}); |
There was a problem hiding this comment.
- {cachekey: M.cfg.jsrev}
+ {cachekey: M.cfg.langrev}As the code has at stringUtils.ts:156,194
| Requests made with a `cachekey` (see [route caching](../../../apis/subsystems/routing/caching.md)) are sent individually, even via a batcher. Hiding them inside a generic `$batch` request would prevent browsers and reverse proxies caching each URL. | ||
|
|
||
| ```js | ||
| const response = await Fetch.getBatcher().performGet('core', 'strings/en/core', {cachekey: M.cfg.jsrev}); |
There was a problem hiding this comment.
- {cachekey: M.cfg.jsrev}
+ {cachekey: M.cfg.langrev}As the code has at stringUtils.ts:156,194
| /api/rest/v2/cachekey:1737584047/strings/en/core # Cacheable | ||
| ``` | ||
|
|
||
| Because the cache key forms part of the URI, changing it (typically by using the current JavaScript/theme revision) invalidates every cached copy of the resource. You do not need to declare the parameter yourself. |
There was a problem hiding this comment.
Suggestion:
- Because the cache key forms part of the URI, changing it (typically by using the current JavaScript/theme revision) invalidates every cached copy of the resource.
+ Because the cache key forms part of the URI, changing it invalidates every cached copy of the resource. Use the revision that changes with the resource: `M.cfg.langrev` for strings, `M.cfg.templaterev` for templates.
|
|
||
| :::danger | ||
|
|
||
| Responses are cached as `public` and `immutable`. Only use `cachelifetime` for routes whose response is identical for every user and which never contains private data. |
There was a problem hiding this comment.
I suggest adding to the danger note:
Responses are cached as `public` and `immutable`. Only use `cachelifetime` for routes whose response is identical for every user and which never contains private data.
+
+ Anything the response varies by, such as the language or the theme, must be part of the path. Caches store responses by URL, so a value sent in a request header is ignored, and every user would get whichever version was requested first.| ## Behaviour notes {/* #behaviour-notes */} | ||
|
|
||
| - If a batch contains a single request, the batch endpoint is _not_ used; it is sent as a normal request. | ||
| - The queue is flushed automatically once it holds more than 20 requests. |
There was a problem hiding this comment.
The check is now >= 20, so a batch holds at most 20 requests rather than "more than 20"

MDL-82652